package cn.yym.test.filter;


import cn.yym.test.domain.User;
import cn.yym.test.service.UserService;
import cn.yym.test.service.impl.UserServiceImpl;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/**
 * 在编写LoginFilter的时候，一定的结合着LoginServlet的代码。
 */
@WebFilter(filterName = "LoginFilter", urlPatterns = "/*")
public class LoginFilter implements Filter {

    private UserService userService = new UserServiceImpl();

    private String[] staticResource = new String[]{".css", ".png", ".jpg", ".js", "css.map"};

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        HttpServletResponse response = (HttpServletResponse)servletResponse;

        /**
        StringBuffer url = request.getRequestURL();  // Uniform resource locator
        String uri = request.getRequestURI();        // Uniform resource identifier

        System.out.println(url.toString());
        System.out.println(uri);
         */
        String uri = request.getRequestURI();
        /**
         如果是 1.登录页面、
               2.访问静态资源、
               3.用户填写完用户名和密码去验证的时候，
               4.因为在web.xml配置了如下信息
                   <welcome-file-list>
                       <welcome-file>login.jsp</welcome-file>
                   </welcome-file-list>
                所以用户直接访问项目的名的时候，直接放其过。 request.getContextPath()是动态的获取项目名，因为项目名是可以更改，所以不能写死.
            一定要注意: 针对第四点，是因为我们配置 web.xml的如上形式，我们才
                uri.endsWith(request.getContextPath()) || uri.endsWith(request.getContextPath() + "/")

             当直接访问 http://localhost:8081/web_project_war_exploded/ 这个地址的时候，其实就是在请求login.jsp, 所以要让其过
             http://localhost:8081/web_project_war_exploded    -> login.jsp
        */
        if(uri.endsWith("login.jsp") || isStaticResource(uri)
                || uri.endsWith("/login") || uri.endsWith(request.getContextPath()) || uri.endsWith(request.getContextPath() + "/")) {
            filterChain.doFilter(request, response);
            return;
        }
        // 如果用户是到登录页面去，就直接放他过去


        // 获取session
        HttpSession session = request.getSession();

        /**
         * 如果用户之前登陆成功过, 那么在LoginServlet中肯定执行过 session.setAttribute("user", user), 并且在
         * session没有超时的情况下，那么obj肯定不为空。
         */
        Object obj = session.getAttribute("user");
        // 如果obj不为空，表示用户登陆成功后，并且一直在操作
        if(null != obj) {
            filterChain.doFilter(request, response);
            return;
        } else {  //如果session不是活动状态: 1. 例如说下班后，就没在该网站一直操作; 2. 浏览器关闭。
            //表示session过期，或者用户浏览器重启了(关联不上服务器端的session), 就要从cookie中去取数据
            Cookie[] cookies = request.getCookies();
            if(null != cookies) {
                String username = null;
                String password = null;
                for(Cookie cookie : cookies) {
                    // 获取cookie的名字，因为一个网站存在很多的cookie
                    String name = cookie.getName();
                    //如果是用户名对应的cookie, 那么说白了用户在登录的时候，勾选了 "记住我" 这个checkbox,
                    // 会在 LoginSerlvet中执行：
                    //           Cookie usernameCookie = new Cookie("username", username);
                    //           resp.addCookie(usernameCookie);
                    if("username".equals(name)) {
                        username = cookie.getValue();
                    }else if("password".equals(name)) {
                        password = cookie.getValue();
                    }
                }

                // TODO 如果用户名和密码不为空，就需要到数据库查询
                if(null != username && null != password) {
                    //在到数据库中校验用户名或者密码是否错误, 因为用户可能换浏览器或者机器，修改了密码。
                    User user = userService.checkUser(username, password);

                    // 表示用户的信息校验成功
                    if(null != user) {
                        // 根据cookie新又重新登录了一次，需要重新设置session
                        session.setAttribute("user", user);
                        filterChain.doFilter(request, response); //接着往后走
                        return;
                    }else {  //用户名或者密码错误了
                        response.sendRedirect("login.jsp");
                        return;
                    }
                }else { // cookie中没有存储用户名和密码
                    response.sendRedirect("login.jsp");
                    return;
                }
            }else {
                response.sendRedirect("login.jsp");
                return;
            }
        }
    }

    @Override
    public void destroy() {

    }

    /**
     * 判断某个请求的资源是否为静态资源, 说白了就是请求的资源后缀是否为：".css", ".png", ".jpg", ".js"
     * uri: /web_project_war_exploded/login.jsp
     *      /web_project_war_exploded/bootstrap.min.css
     */
    private boolean isStaticResource(String uri) {
        for(String str : staticResource) {
            if(uri.endsWith(str)) {
                return true;
            }
        }
        return false;
    }
}
